package com.hangxintong.common.utils;

import cn.hutool.core.util.StrUtil;
import com.hangxintong.common.base.entity.LmUser;
import com.hangxintong.common.exception.SystemErrorCodeMark;
import com.hangxintong.common.exception.SystemException;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.regex.Pattern.compile;

/**
 * @author Lenovo
 */
@Data
@ApiModel(value="基础返回类",description="基础返回类")
public class Result<T> {

    protected boolean flag;

    // 状态码
    @ApiModelProperty(example="200")
    protected Integer code;

    // 业务提示语
    @ApiModelProperty(example="成功")
    protected String message;
    // 数据对象
    protected Object data;

    public Result() {
    }

    public Result(boolean flag, Integer code, String message) {
        this.flag = flag;
        this.code = code;
        this.message = message;
    }

    public Result(boolean flag, Integer code, String message, Object data) {
        this.flag = flag;
        this.code = code;
        this.message = message;
        this.data = data;
    }




    /**
     * 返回一个默认的 成功操作 的结果，默认响应状态码 200
     *
     * @return 成功操作的实例对象
     */
    public static Result ok(Object data) {
        return new Result(true, 200, "操作成功", data);
    }

    public static Result ok() {
        return new Result(true, 200, "操作成功");
    }

    public static Result msg(String msg) {
        return new Result(false, 500, msg);
    }
    public static Result msg(String msg, Object data) {
        return new Result(false, 500, msg,data);
    }

    public static Result show(Integer code, String message, Object data) {
        return new Result(true, code, message, data);
    }

    public static Result show(Integer code, String message) {
        return new Result(true, code, message, null);
    }



    /**
     * 返回一个默认的 失败操作 的结果，默认响应状态码为 500
     *
     * @return 失败操作的实例对象
     */
    public static Result error(Object data) {
        return new Result(false, 500, "操作失败", data);
    }

    public static Result error() {
        return new Result(false, 200, "操作失败");
    }

    /*
     * 将时间转换为时间戳
     */
    public static Integer dateToStamp(String s) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String res = "";
        if (!"".equals(s)) {
            try {
                res = String.valueOf(sdf.parse(s).getTime() / 1000);
            } catch (Exception e) {
                System.out.println("传入了null值");
            }
        } else {
            long time = System.currentTimeMillis();
            res = String.valueOf(time / 1000);
        }

        return new Integer(res);
    }
    /**
     * 日期格式字符串转换成时间戳
     * @param format 如：yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String date2TimeStamp(String date_str,String format){
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return String.valueOf(sdf.parse(date_str).getTime()/1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
    /**
     * 在原有的时间上添加几个月
     * @author Mr.zhang
     * @date 2020/7/14 18:10
    */
    public static Date stepMonth(Date sourceDate, int month) {
        Calendar c = Calendar.getInstance();
        c.setTime(sourceDate);
        c.add(Calendar.MONTH, month);

        return c.getTime();
    }

    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(int time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String times = format.format(new Date(time * 1000L));
//	    System.out.println("日期格式---->" + times);
        return times;
    }

    /**
     * 去掉首尾指定字符
     *
     * @author Mr.zhang
     * @date 2020/6/4 15:19
     */
    public static String trimBothEndsChars(String srcStr, String splitter) {
        String regex = "^" + splitter + "*|" + splitter + "*$";
        return srcStr.replaceAll(regex, "");
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static String getTime() {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //System.out.println("格式化输出：" + sdf.format(d));
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        //System.out.println("Asia/Shanghai:" + sdf.format(d));
        return sdf.format(d);
    }
    /**
     * 获取当前时间
     *
     * @return
     */
    public static String getDate() {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //System.out.println("格式化输出：" + sdf.format(d));
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        //System.out.println("Asia/Shanghai:" + sdf.format(d));
        return sdf.format(d);
    }
    public static String getDateTime() {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //System.out.println("格式化输出：" + sdf.format(d));
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        //System.out.println("Asia/Shanghai:" + sdf.format(d));
        return sdf.format(d);
    }
    /**
     * 获取当前时间Date
     *
     * @return
     */
    public static Date getTime(Date date) {
        SimpleDateFormat dsf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//格式化规则

        String strDate = dsf.format(date); //格式化成yyyy-MM-dd格式的时间字符串
        Date d = null;
        try {
            if (date == null) {
                d = new Date();
            } else {
                d = dsf.parse(strDate);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        java.sql.Date resultDate = new java.sql.Date(d.getTime());//最后转换成 java.sql.Date类型数据就可以了 注意：最开始时间数据类型是 java.util.Date类型  
        return resultDate;
    }

    /**
     * @return Boolean true\ false
     * @Description 正则验证手机号
     * @Author Bz.Mr
     * @Date 2019/12/20 13:54
     */
    public static boolean validatePhone(String phone) {
        String regExp = "^((1[3-9]))\\d{9}$";
        Pattern compile = compile(regExp);
        Matcher m = compile.matcher(phone);
        return m.matches();
    }

    public static boolean checkEmail(String email) {
        boolean flag = false;
        try {
            String check = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
            Pattern regex = compile(check);
            Matcher matcher = regex.matcher(email);
            flag = matcher.matches();
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }


    public List<T> listClear(List<T> list) {
        Set set = new HashSet();
        set.addAll(list);
        list.clear();
        list.addAll(set);
        return list;
    }

    public Boolean listHas(List<T> list, T t) {
        for (T s : list) {
            if (s.equals(t)) {
                return true;
            }
            if (s == t) {
                return true;
            }
        }
        return false;
    }

    /**
     * @name 字符串转集合
     * @user Mr.zhang
     * @date 2019/12/24 15:46
     */
    public static List<Long> stringToLongList(String strArr) {
        return Arrays.stream(strArr.split(","))
                .map(s -> Long.parseLong(s.trim()))
                .collect(Collectors.toList());
    }

    /**
     * @param strArr
     * @return
     */
    public static List<String> stringToStringList(String strArr) {
        return Arrays.stream(strArr.split(","))
                .map(s -> s.trim())
                .collect(Collectors.toList());
    }

    /*
        字符串时间转date时间
     */
    public static Date StringDate(String time) {
        //String time = "2019-07-23";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date dateTime = null;
        try {
            dateTime = simpleDateFormat.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return dateTime;
    }

    // 字符串转时间格式   年月日
    public static Date parse(String strDate) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date dateTime = null;
        try {
            dateTime = simpleDateFormat.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return dateTime;
    }

    //计算年龄   或者计算与当前时间差
    public static int getAgeByBirth(Date birthDay) {
        int age = 0;
        Calendar cal = Calendar.getInstance();
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth){ age--;}//当前日期在生日之前，年龄减一
            } else {
                age--;//当前月份在生日之前，年龄减一
            }
        }
        return age;
    }

    /**
     *  * 判断是否是日期的格式：yyyy-mm-dd hh-mi-mm 2017-07-31 00:00:00
     *  * @Author  Bz.Mr
     *  * @param timeStr
     *  * @return
     *  
     */
    public static boolean isDateFormat(String timeStr, int a) {
        String regex = "";
        if (a == 0) {
            regex = "\\d{4}-\\d{2}-\\d{2}";
        } else {
            regex = "\\d{4}-\\d{2}-\\d{2}\\s{1}\\d{2}:\\d{2}:\\d{2}";
        }

        // 编译正则表达式
        Pattern pattern = compile(regex);
        // 忽略大小写的写法
        //Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(timeStr);
        return matcher.matches();
    }

    /**
     * 生成uuid
     *
     * @return
     */
    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 生成课程唯一编码
     *
     * @return
     */
    public static int pieceUnique() {
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if (hashCodeV < 0) {//有可能是负数
            hashCodeV = -hashCodeV;
        }
        return hashCodeV;
    }

    /**
     * @Description
     * @Author Bz.Mr
     * @Date 2020/6/3 14:49
     * 生成六位数
     */
    public static int sixRandom() {
        return (int) ((Math.random() * 9 + 1) * 100000);
    }

    // 生成订单号
    public static String getOrderIdByTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String newDate = sdf.format(new Date());
        String result = "";
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            result += random.nextInt(10);
        }
        return newDate + result;
    }

    /**
     * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？
     * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
     * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130,
     *
     * @param request
     * @return
     * @Mr-Bz 用户真实IP为： 192.168.1.110
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }


    /**
     * 将短时间格式字符串转换为时间  yyyy-MM-dd yyyy-MM-dd HH:ii::ss
     *
     * @param strDate
     * @return
     */
    public static Date strToDate(String strDate,String dateType) {
       SimpleDateFormat formatter = new SimpleDateFormat(dateType);
       ParsePosition pos = new ParsePosition(0);
       Date strtodate = formatter.parse(strDate, pos);
       return strtodate;
    }


    /**date
     * @param request
     * @return
     */
    public static Long getUid(HttpServletRequest request) {
        String uid = request.getHeader("uid");
        if (org.springframework.util.StringUtils.isEmpty(uid)) {
            throw new SystemException(SystemErrorCodeMark.Code.SYS_0001, "协会信息不存在");
        }
        return Long.parseLong(uid);
    }

    /**
     * @Description
     * @Author Bz.Mr
     * @Date 2020/5/18 17:57
     */
    public static String getDateToString(Date addtime) {
        if (addtime == null) {return null;}
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String strTime = sdf.format(addtime);
        return strTime;
    }

    /**
     * @param param
     * @return
     */
    public static Object toString(Object param) {
        return (param == null || param.equals("")) ? "" : param;
    }

    /**
     * 不为空的对象转换为字符串
     * @param param
     * @return
     */
    public static String ifNulltoString(Object param) {
        return (param == null || param.equals("")) ? "" : param.toString();
    }
    /**
     * 验证省份证号
     *
     * @param IDNumber
     * @return
     */
    public static boolean isIDNumber(String IDNumber) {
        if (IDNumber == null || "".equals(IDNumber)) {
            return false;
        }
        // 定义判别用户身份证号的正则表达式（15位或者18位，最后一位可以为字母）
        String regularExpression =
                "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|"
                        + "(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
        boolean matches = IDNumber.matches(regularExpression);
        // 判断第18位校验值
        if (matches) {
            if (IDNumber.length() == 18) {
                try {
                    char[] charArray = IDNumber.toCharArray();
                    // 前十七位加权因子
                    int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
                    // 这是除以11后，可能产生的11位余数对应的验证码
                    String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
                    int sum = 0;
                    for (int i = 0; i < idCardWi.length; i++) {
                        int current = Integer.parseInt(String.valueOf(charArray[i]));
                        int count = current * idCardWi[i];
                        sum += count;
                    }
                    char idCardLast = charArray[17];
                    int idCardMod = sum % 11;
                    if (idCardY[idCardMod].toUpperCase()
                            .equals(String.valueOf(idCardLast).toUpperCase())) {
                        return true;
                    } else {
//                        System.out.println("身份证最后一位:" + String.valueOf(idCardLast).toUpperCase()
//                                + "错误,正确的应该是:" + idCardY[idCardMod].toUpperCase());
                        return false;
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
            } else {
                return false;
            }
        }
        return matches;
    }

    /**
     * 验证身份证号
     *
     * @param idCard
     * @return
     */
    public static boolean isIdCard(String idCard) {

        String regExp = "^\\d{15}|^\\d{17}([0-9]|X|x)$";
        Pattern compile = compile(regExp);
        Matcher m = compile.matcher(idCard);
        return m.matches();
    }

    /**
     * 验证手机号
     *
     * @param isMobile
     * @return
     */
    public static boolean isMobile(String isMobile) {

        String regExp = "^((1[3-9]))\\d{9}$";
        Pattern compile = compile(regExp);
        Matcher m = compile.matcher(isMobile);
        return m.matches();
    }

    /**
     * 统计某字符在字符串中出现的位置
     *
     * @param srcStr
     * @param findStr
     * @return
     * @author mxf 2020-06-24
     */
    public static int countStrNum(String srcStr, String findStr) {
        int count = 0;
        Pattern pattern = compile(findStr);// 通过静态方法compile(String regex)方法来创建,将给定的正则表达式编译并赋予给Pattern类
        Matcher matcher = pattern.matcher(srcStr);//
        while (matcher.find()) {// boolean find() 对字符串进行匹配,匹配到的字符串可以在任何位置
            count++;
        }
        return count;
    }

    /**
     * 省份证的正则表达式^(\d{15}|\d{17}[\dx])$
     *
     * @param id 省份证号
     * @return 生日（yyyy-MM-dd）
     */
    public static String extractYearMonthDayOfIdCard(String id) {
        String year = null;
        String month = null;
        String day = null;
        //正则匹配身份证号是否是正确的，15位或者17位数字+数字/x/X
        if (id.matches("^\\d{15}|\\d{17}[\\dxX]$")) {
            year = id.substring(6, 10);
            month = id.substring(10, 12);
            day = id.substring(12, 14);
        } else {
            System.out.println("身份证号码不匹配！");
            return null;
        }
        return year + "-" + month + "-" + day;
    }

    /**
     * 验证联系方式
     *
     * @param contact
     * @return
     */
    public static boolean validateContact(String contact) {
        if (StrUtil.isEmpty(contact)) {
            return false;
        }
        String regexp1 = "/0\\\\d{2,3}-\\\\d{7,8}/";
        String regexp2 = "^((1[3-9]))\\d{9}$";
        Pattern compile = compile(regexp1);
        Matcher m = compile.matcher(contact);

        Pattern compile1 = compile(regexp2);
        Matcher m2 = compile1.matcher(contact);
        if (!m.matches() || !m2.matches()) {
            return false;
        }
        return true;
    }

    /**
     * 验证金额格式
     * @param money
     * @return
     */
    public static boolean validateMoney(BigDecimal money){
        String regExp = "^(([1-9]{1}\\\\d*)|([0]{1}))(\\\\.(\\\\d){0,2})?$";
        Pattern compile = compile(regExp);
        Matcher m = compile.matcher(money.toString());
        return m.matches();
    }

    /**
     * 功能：判断字符串是否为日期格式
     *
     * @param strDate
     * @return
     */
    public static boolean isDate(String strDate) {
        Pattern pattern = compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
        Matcher m = pattern.matcher(strDate);
        if (m.matches()) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * @param request
     * @return
     */
    public static Long getUserId(HttpServletRequest request) {
        LmUser user = (LmUser) request.getAttribute("user");
        if (user == null) {
            user = new LmUser();
            user.setId((long)1);
        }
        return user.getId().longValue();
    }

    public static int timeCompareTo(String s1,String s2){
//        String s1="2008-01-25 09:12:09";
//        String s2="2008-01-29 09:12:11";
        java.text.DateFormat df=new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        java.util.Calendar c1=java.util.Calendar.getInstance();
        java.util.Calendar c2=java.util.Calendar.getInstance();
        try{
            c1.setTime(df.parse(s1));
            c2.setTime(df.parse(s2));
        }catch(java.text.ParseException e){
            System.err.println("格式不正确");
        }
        int result=c1.compareTo(c2);
        if(result==0)
            System.out.println("c1相等c2");
        else if(result<0)
            System.out.println("c1小于c2");
        else
            System.out.println("c1大于c2");
        return result;
    }
}
